home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / hypercar / xfcn / spttool.cpt / Support Tools eXternals 1.2.5 / card_34896.txt < prev    next >
Text File  |  1990-11-13  |  18KB  |  440 lines

  1. -- card: 34896 from stack: in.5
  2. -- bmap block id: 10487
  3. -- flags: 0000
  4. -- background id: 3858
  5. -- name: FileVersion
  6. ----- HyperTalk script -----
  7. on HideObjects
  8.   hide cd btn "Try It!"
  9. end HideObjects
  10.  
  11. on ShowObjects
  12.   show cd btn "Try It!"
  13. end ShowObjects
  14.  
  15.  
  16. -- part 1 (button)
  17. -- low flags: 00
  18. -- high flags: A002
  19. -- rect: left=82 top=185 right=219 bottom=175
  20. -- title width / last selected line: 0
  21. -- icon id / first selected line: 0 / 0
  22. -- text alignment: 1
  23. -- font id: 0
  24. -- text size: 12
  25. -- style flags: 8192
  26. -- line height: 16
  27. -- part name: Try it!
  28. ----- HyperTalk script -----
  29. on mouseUp
  30.   global errGlobal
  31.   put FilePath("", "Choose a file please.") into fileName
  32.   if fileName = empty then exit mouseUp
  33.   set cursor to watch
  34.   put FileVersion(fileName, "nodialog:errGlobal") into fVersion
  35.   if errGlobal Γëá empty then
  36.     answer "Error: ΓÇ£" & errGlobal & "ΓÇ¥"
  37.     put empty into errGlobal
  38.   else
  39.     if fVersion Γëá empty then
  40.       answer "The version info for ΓÇ£" & fileName & "ΓÇ¥ is:" & return & return & fVersion
  41.     else
  42.       answer "No version info for ΓÇ£" & fileName & "ΓÇ¥."
  43.     end if
  44.   end if
  45. end mouseUp
  46.  
  47.  
  48.  
  49.  
  50. -- part contents for background part 38
  51. ----- text -----
  52. 21/50
  53.  
  54. -- part contents for background part 20
  55. ----- text -----
  56. FileVersion - An XFCN to return the version string of a specified file
  57.  
  58. FileVersion(pathname, <"noDialog:errorGlobal">)
  59.  
  60. This XFCN will return the version string from the specified file.  This is the string you see when selecting "Get Info" from the Finder's File menu.  Nothing is returned if there is no version information.
  61.  
  62.  
  63. -- part contents for background part 42
  64. ----- text -----
  65. { FileVersion(pathname ┬½,"nodialog":errGlobal┬╗)             }
  66. {}
  67. { XFCN to return the creation date for the file/folder         }
  68. { specified by the path given in the first parameter.       }
  69. {}
  70. {   Written by:      Anup Murarka             Eric Carlson         }
  71. {               ALINK:  SKEPTIC           ALINK:  cyNic   }
  72. {                               CIS:  76004,3356         }
  73. {}
  74. {               We are part of the Support Tools Development Group,     }
  75. {               Apple Computer, Inc.      }
  76. {}
  77. {               please DO NOT contack Mac DTS for support of this code!    }
  78. {}
  79. {               please DO contact the authors for support of this code!     }
  80. {}
  81. {               Send comments, bug reports, requests to any of the above   }
  82. {               E-mail addresses or to:}
  83. {}
  84. {                           (one of us)                  }
  85. {                           Apple Computer, Inc.          }
  86. {                           900 E. Hamilton, Ave.          }
  87. {                           Campbell, CA   95008      }
  88. {                           M/S 72-L                     }
  89. {}
  90. {   Copyright:   ┬⌐ 1989, 1990 by Apple Computer, Inc., all rights reserved.     }
  91. {}
  92. { written by    : Anup Murarka                                                                               }
  93. { AppleLink  : Skeptic                                                                                      }
  94. { modification history                                                                                        }
  95. {          Date                Initials                                  Comments                               }
  96. {          ----            ------        -----------------------------------------------------}
  97. {       8/16/89           akm         first written                                                                       }
  98. {       5/21/90           ec            removed upper case converion for A/UX compatibility.   }
  99. {                                           Changed version to 1.1.  Corrected code which was                }
  100. {                                           looking for ΓÇ£VERSΓÇ¥ resource to look for ΓÇ£versΓÇ¥ type.           }
  101. {                                           added ΓÇ£ExtractLongVersΓÇ¥ function to avoid byte                     }
  102. {                                           alignment problems.  correct potential error in file type        }
  103. {                                           calculation.  added more error reporting                                  }
  104. {       5/24/90           ec            set resload to false before opening file to avoid preloading}
  105. {                                           any resources, explicitly set resload to true before            }
  106. {                                           trying to load the vers resource                                           }
  107. {}
  108. unit FileVersion;
  109.  
  110. interface
  111.  
  112.     uses
  113.         HyperXCMD;
  114. {    , MiscUtils , XCmdIncludes}
  115.  
  116.     procedure MAIN (paramPtr: XCmdPtr);
  117.  
  118. implementation
  119.     type
  120.     { TN#189 has all of the version declarations used below}
  121.         NumVersion = packed record
  122.                 case integer of
  123.                     0: (
  124.                             majorRec: signedByte;
  125.                             minorRev: 0..9;
  126.                             bugFixRev: 0..9;
  127.                             stage: SignedByte;
  128.                             nonRelRev: SignedByte
  129.                     );
  130.                     1: (
  131.                             version: longint
  132.                     );
  133.             end;
  134.  
  135.         VersRec = record
  136.                 case integer of
  137.                     0: (
  138.                             numericVersion: NumVersion;
  139.                             countryCode: integer;
  140.                             shortVersion: str255;
  141.                             longVersion: str255;
  142.                     );      {longVersion is named RESERVED in the TN.}
  143.  
  144.                     {This variant is used to also describe the old version information      }
  145.                     {format where the file (usually of type APPL) had a resource of        }
  146.                     {type fileCreator that contained the info string.                     }
  147.                     1: (
  148.                             VersionData: str255;
  149.                     )
  150.             end;
  151.         VersRecPtr = ^VersRec;
  152.         VersRecHandle = ^VersRecPtr;
  153.  
  154.     procedure FileVersion (paramPtr: XCmdPtr);
  155.     FORWARD;
  156.  
  157.     procedure MAIN (paramPtr: XCmdPtr);
  158.     begin
  159.         FileVersion(paramPtr);
  160.     end;
  161.  
  162.     procedure ReportToUser (paramPtr: XCmdPtr; msgStr: str255);
  163. {}
  164. { report something back to the user.  }
  165. { the last parameter (optional) to an external may contain }
  166.  { "noDialog" or "noDialog:GlobalName".  GlobalName is the name }
  167.  { of a HyperTalk global variable into which error messages will be }
  168.  { placed.  we've decided to use this approach to avoid confusing }
  169. { an error message with a valid result being returned from an XFCN. }
  170. {}
  171.         var
  172.             tempStr: str255;
  173.     begin
  174. {check the last param to see if the user requested that}
  175. { we suppress the error dialog }
  176.         ZeroToPas(paramPtr, paramPtr^.params[paramPtr^.paramCount]^, tempStr);
  177.         UprString(tempStr, true);
  178.         if pos('NODIALOG', tempStr) = 0 then
  179.     { no special error handling specified, throw up a dialog and return the error message }
  180.             begin
  181.                 SendCardMessage(paramPtr, concat('answer "', msgStr, '"'));
  182.                 paramPtr^.returnValue := PasToZero(paramPtr, msgStr);
  183.             end
  184.         else if (pos(':', tempStr) > 0) then
  185.     { requested global AND noDialog so we fill in the global and return empty }
  186.             begin
  187.                 tempStr := copy(tempStr, pos(':', tempStr) + 1, length(tempStr));
  188.                                                         { get the name of the HC global  to fill }
  189.                 SetGlobal(paramPtr, tempStr, PasToZero(paramPtr, msgStr));
  190.                                                         { and fill it }
  191.                 paramPtr^.returnValue := PasToZero(paramPtr, '');      { return empty }
  192.             end
  193.         else
  194.     { requested noDialog only so we return the error condition as the result }
  195.             paramPtr^.returnValue := PasToZero(paramPtr, msgStr);
  196.     end;     { procedure }
  197.  
  198.     function AskedForHelp (paramPtr: XCmdPtr; syntaxMsg: Str255; copyrightMsg: Str255): boolean;
  199. {   check to see if the user sent a '?' or a '!' as }
  200. { the only parameter. if so we will respond with }
  201. { the calling syntax or the copyright/version info }
  202. { for this external }
  203. {}
  204.         var
  205.             firstStr: str255;
  206.     begin
  207.         askedForHelp := false;
  208.         if paramPtr^.paramCount = 1 then
  209.             begin
  210.                 ZeroToPas(paramPtr, paramPtr^.params[1]^, firstStr);
  211.                     { what is the first param? }
  212.                 if firstStr = '?' then
  213.                     begin
  214.                         reportToUser(paramPtr, syntaxMsg);
  215.                         askedForHelp := true
  216.                     end  { asked for help }
  217.                 else if firstStr = '!' then
  218.                     begin
  219.                         reportToUser(paramPtr, copyRightMsg);
  220.                         askedForHelp := true
  221.                     end;     { asked for copyright info }
  222.             end;     { one parameter passed }
  223.     end;     { function }
  224.  
  225.     function NumberToString (paramPtr: XCmdPtr; num: LONGINT): Str255;
  226. { use the toolbox call rather than HC's }
  227.         var
  228.             tempStr: str255;
  229.     begin
  230.         NumToString(num, tempStr);
  231.         NumberToString := tempStr;
  232.     end;
  233.  
  234.     procedure reportResError (paramPtr: XCmdPtr; errorNum: integer);
  235.         var
  236.             errMsg, tempName: str255;
  237.     begin
  238.         case errorNum of                   { what caused the problem? }
  239.             -0: 
  240.                 errMsg := 'no error.';
  241.             -36: 
  242.                 errMsg := 'I/O Error.';
  243.             -37: 
  244.                 errMsg := 'bad file name or volume name.';
  245.             -38: 
  246.                 errMsg := 'file not open.';
  247.             -39: 
  248.                 errMsg := 'that file has no resource fork.';
  249.             -42: 
  250.                 errMsg := 'too many files open.';
  251.             -43: 
  252.                 errMsg := 'file not found.';
  253.             -45, -54, -61: 
  254.                 errMsg := 'file locked.';
  255.             -47, -49: 
  256.                 errMsg := 'file is busy.';
  257.             -53: 
  258.                 errMsg := 'that volume is not on line.';
  259.             -108: 
  260.                 errMsg := 'not enough room in heap zone.';
  261.             -120: 
  262.                 errMsg := 'directory not found.';
  263.             -121: 
  264.                 errMsg := 'too many working directories open.';
  265.             -127: 
  266.                 errMsg := 'internal file system error.';
  267.             -192: 
  268.                 errMsg := 'resource not found.';
  269.             -193: 
  270.                 errMsg := 'file not found.';
  271.             otherwise
  272.                 errMsg := concat('unexpected error #', NumberToString(paramPtr, errorNum));
  273.         end;         { case }
  274.  
  275.         errMsg := concat('Sorry, ', errMsg);
  276.         reportToUser(paramPtr, errMsg);
  277.         { return the error message }
  278.     end;         { function }
  279.  
  280.     function getParams (paramPtr: XCmdPtr; var PathToFile: str255): boolean;
  281.     { function to get the parameters and validate them.  Returns boolean}
  282.     { instructing the main procedure to continue if the parameters passed}
  283.     { are valid.  Also returns syntax messages if requested by the user.}
  284.         var
  285.             numParams: integer;
  286.             syntaxStr, copyrightStr: str255;
  287.     begin
  288.         getParams := true;     {Initially, assume the parameters are valid.}
  289.         syntaxStr := 'FileVersion(pathname ┬½, ΓÇ£nodialogΓÇ¥:errGlobal┬╗)';
  290.         copyrightStr := '┬⌐ 1989, 1990 Apple Computer, Inc., v.1.1, by Anup Murarka';
  291.  
  292.         {check that we have the proper number of parameters}
  293.         numParams := paramPtr^.paramCount;
  294.         if (numParams < 1) or (numParams > 2) then
  295.             begin
  296.                 getParams := false;
  297.                 reportToUser(paramPtr, syntaxStr);
  298.                 exit(getParams);
  299.             end;
  300.  
  301.         if AskedForHelp(paramPtr, syntaxStr, copyrightStr) then
  302.             begin
  303.                 getParams := false;
  304.                 exit(getParams);
  305.             end;
  306.  
  307.         { Get first parameter}
  308.         ZeroToPas(paramPtr, paramPtr^.Params[1]^, PathToFile);
  309.     end;         {GetParams}
  310.  
  311.     function ExtractLongVers (versHndl: VersRecHandle): str255;
  312. { use a block move to grab the data as it may not be byte aligned - pascal doesn't like that! }
  313. {  see tech note #189 }
  314.         var
  315.             msgPtr: StringPtr;
  316.             theMsg: str255;
  317.     begin
  318.         theMsg := '';
  319.         if versHndl <> nil then
  320.             begin
  321.                 HLock(Handle(versHndl));           { lock our handle }
  322.                 with versHndl^^ do
  323.                     begin
  324.                 { calc a pointer to the long message }
  325.                         msgPtr := StringPtr(Ord(@shortVersion) + Length(shortVersion) + 1);
  326.                 { and move the data into our string }
  327.                         BlockMove(Ptr(msgPtr), @theMsg, Length(msgPtr^) + 1);
  328.                     end;
  329.                 HUnLock(Handle(versHndl));           { unlock our handle now that we've finished }
  330.             end;
  331.         ExtractLongVers := theMsg;
  332.     end;
  333.  
  334.     function BitTest (AddressToCheck: ptr; TotalBits: integer; BitToTest: longint): boolean;
  335.     { function that allows caller to use std. 68000 bit notation instead of the Toolbox's reversed notation}
  336.     { example:  bit 0 (the least significant bit) in a byte is bit 7 in the Toolbox's notation}
  337.     begin
  338.         BitTest := BitTst(AddressToCheck, TotalBits - 1 - BitToTest);
  339.     end;
  340.  
  341.     function CurResLoad: boolean;
  342.     { return the current setting of the system 'ResLoad'.  Are resources }
  343.     { actually loaded or not?}
  344.         const
  345.             ResLoad = $A5E;          { determines whether or not resources are pre-loaded}
  346.         type
  347.             booleanPtr = ^boolean;
  348.     begin
  349.         curResLoad := booleanPtr(ResLoad)^
  350.     end;
  351.  
  352.     procedure FileVersion (paramPtr: XCmdPtr);
  353.         var
  354.             getParamsOK, origResLoad: boolean;
  355.             fileRefNum, oldfileRefNum, charNdx: integer;
  356.             fileName, fileCreator: str255;
  357.             paramBlock: CInfoPBRec;
  358.             errorCode: OSerr;
  359.             versionStr: str255;
  360.             versDataHndl: VersRecHandle;
  361.  
  362.     begin   { FileVersion}
  363.     { fetch and validate the passed parameters}
  364.         getParamsOK := getParams(paramPtr, FileName);
  365.         if not (getParamsOK) then
  366.             exit(FileVersion);
  367.  
  368.     { Initialize the parameter block.  Since we have the full pathname, no other field is really needed.}
  369.         zeroBytes(paramPtr, @paramBlock, sizeOf(paramBlock));
  370.         paramBlock.ioNamePtr := @FileName;
  371.         errorCode := PBGetCatInfo(@paramBlock, FALSE);
  372.         if errorCode <> noErr then
  373.             begin
  374.                 reportToUser(paramPtr, 'Sorry, file not found.');
  375.                 exit(FileVersion);
  376.             end;
  377.  
  378.     { Make sure it is a file and not a folder}
  379.         if bitTest(@paramBlock.ioFlAttrib, 8, 4) then
  380.             begin
  381.                 reportToUser(paramPtr, 'Sorry, directories do not have ΓÇÿversΓÇÖ resources!');
  382.                 exit(FileVersion);
  383.             end;
  384.  
  385.         oldfileRefNum := CurResFile;                          { remember which resource file is current }
  386.         origResLoad := CurResLoad;                       { the current setting of ResLoad }
  387.         SetResLoad(false);                                      { avoid slow preloads when we open the resource fork }
  388.         fileRefNum := OpenRFPerm(filename, 0, fsRdPerm);
  389.         SetResLoad(true);                                   { make sure we can load the resource we need }
  390.         if (resError <> noErr) and (resError <> -39) then    { no error or no resource fork }
  391.             begin
  392.                 reportResError(paramPtr, resError);         { report the error }
  393.                 SetResLoad(origResLoad);                          {  restore the setting before leaving }
  394.                 exit(FileVersion);
  395.             end;
  396.  
  397.         if resError = -39 then                                 { the file has no resource fork, thus it can't have a vers resource }
  398.             begin
  399.                 SetResLoad(origResLoad);                          {  restore the setting before leaving }
  400.                 paramPtr^.returnValue := PasToZero(paramPtr, '');      { no vers, return nothing }
  401.                 exit(FileVersion);
  402.             end;
  403.  
  404.         UseResFile(fileRefNum);                             { use the correct resource fork }
  405.  
  406.         versionStr := '';
  407.         { check ΓÇ£versΓÇ¥ resource id 1, if there is none then check ΓÇ£versΓÇ¥ resource id 2,  if still don't find anything }
  408.         {   check resource with the file's creator string (ie. WILD).  the later is the old style of storing version info }
  409.         if Count1Resources('vers') > 0 then
  410.             begin           { check for vers id 1 }
  411.                 VersDataHndl := VersRecHandle(Get1IndResource('vers', 1));
  412.                 if VersDataHndl <> nil then
  413.                     VersionStr := ExtractLongVers(VersDataHndl)
  414.                 else
  415.                     begin           { check for vers id 2 }
  416.                         VersDataHndl := VersRecHandle(Get1IndResource('vers', 2));
  417.                         if VersDataHndl <> nil then
  418.                             VersionStr := ExtractLongVers(VersDataHndl);
  419.                     end;     { checking for vers id 2 }
  420.             end;
  421.         fileCreator := '1234';           { grab the file type }
  422.         for charNdx := 1 to 4 do
  423.             fileCreator[charNdx] := paramBlock.ioFlFndrInfo.fdCreator[charNdx];
  424.         if (VersionStr = '') and (Count1Resources(fileCreator) > 0) then
  425.             begin                                       { try the type resource for the 'old style' version data }
  426.                 VersDataHndl := VersRecHandle(Get1IndResource(fileCreator, 1));
  427.                 if VersDataHndl <> nil then
  428.                     VersionStr := VersDataHndl^^.VersionData;
  429.             end;
  430.  
  431.     {CleanUp}
  432.         SetResLoad(origResLoad);                      {  restore the setting before leaving }
  433.         UseResFile(oldfileRefNum);                    { reset the proper resource file order }
  434.         CloseResFile(fileRefNum);                  { close the file we opened }
  435.  
  436.     { Now prepare the return value}
  437.         paramPtr^.returnValue := PasToZero(paramPtr, VersionStr);
  438.     end;
  439.  
  440. end.